home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************/
- /*
- C de Cerca 4
- Recursos: WIND y ALRT
- Rafael Escoté - Enric Herrera
- BlauSoft S.L. para MacFormat España - 1996
-
- La descripción del código y la información sobre cómo preparar
- el entorno de programación y generar estos programas, está contenida
- en el ejemplar de MacFormat que los acompaña.
-
- */
- /*****************************************************************/
-
-
-
- /*
- LA TOOLBOX Y LOS FICHEROS 'UNIVERSAL HEADERS'
- ==============================================
- La Toolbox es una colección de funciones escritas por Apple
- que han sido ya compiladas y colocadas en los chips de ROM de cada
- Mac.
- Para poder emplear en nuestros programas una de dichas funciones,
- debemos informar al compilador acerca de los posibles parámetros
- y valores de salida requeridos.
- En otras palabras, el compilador necesita el prototipo de la función
- existente en la Toolbox de forma que pueda verificar que el uso que de
- ella hagamos en nuestro programa sea correcto.
- Los ficheros APPLE UNIVERSAL HEADERS proporcionados por Apple no
- son más que ficheros de texto conteniendo los prototipos de cada una de
- las funciones de la Toolbox.
-
- NOTA: Sólo para los más curiosos: En la carpeta que contiene el compilador,
- veréis una carpeta llamada 'MacOS Support' y en su interior una carpeta
- llamada 'Headers' y dentro de ella una carpeta llamada
- 'Universal Headers', que contiene todos los ficheros creados por Apple.
- */
-
-
-
- /*
- COMO DIFERENCIAR FUNCIONES PROPIAS Y DE LA TOOLBOX
- ===================================================
- A las funciones creadas por nosotros para este programa (y que por lo
- tanto no pertenecen a la Toolbox) les hemos dado nombres que comienzan
- por las iniciales MF. Por ejemplo, MF_PlaySnd(), MF_RandomColor() etc...
- Todas las restantes funciones que aparecen empleadas en el código, SON
- FUNCIONES PERTENECIENTES A LA TOOLBOX DE APPLE.
- (Una excepción: La función main() la hemos creado nosotros pero su nombre
- no puede ser otro que main(), por convención)
-
-
-
- /**************************************************************** */
- /* PROTOTIPOS DE LAS FUNCIONES QUE HEMOS CREADO */
- /* PARA NUESTRO PROGRAMA */
- /**************************************************************** */
- void main(void); /* Esta función NO puede tener otro nombre */
- void MF_InitToolbox (void);
- void MF_SetupMenus (void);
- void MF_AbreMiVentana (void);
- void MF_EscribeTexto (void);
- void MF_bucle_principal(void);
- void MF_MenuBar (long algoSeleccionado);
- void MF_Update (WindowPtr ventana_a_refrescar);
-
-
-
- /**************************************************************** */
- /* CONSTANTES Y VARIABLES GLOBALES */
- /* DE USO GENERAL */
- /**************************************************************** */
- Boolean gAcabarProg = false; /* Una variable global.
- Como siempre, las variables globales
- las prefijamos con la letra 'g'.
- Cuando gAcabarProg sea = true,
- acabaremos el programa */
-
-
-
- /**************************************************************** */
- /* CONSTANTES DEFINIENDO EL NUMERO DE RECURSO (resource) */
- /* CORRESPONDIENTE A LA VENTANA DE ALERTA QUE ABRIREMOS */
- /* CUANDO EL USUARIO SELECCIONE 'Acerca de C de Cerca...' */
- /* DEL MENU Apple
- /**************************************************************** */
- #define kAlertRsrcID 128 /* Nº del recurso ALRT */
-
-
-
- /**************************************************************** */
- /* CONSTANTES Y VARIABLES GLOBALES */
- /* RELACIONADAS CON LOS MENUS EN NUESTRO PROGRAMA */
- /**************************************************************** */
- #define kAppleMenuID 128 /* Nuevo recurso MENU para el menú Apple */
- #define kArchivoMenuID 129
- #define kAcercaDe_Item 1
- #define kSalirItem 1
-
- MenuRef gAppleMenu;
- MenuRef gArchivoMenu;
-
-
-
- /**************************************************************** */
- /* CONSTANTES Y VARIABLES GLOBALES */
- /* RELACIONADAS CON LA VENTANA QUE ABRIREMOS */
- /**************************************************************** */
- /* A diferencia de las versiones anteriores, en esta, la ventana que
- abriremos la hemos creado previamente empleando ResEdit y formará
- parte de los recursos de la aplicación */
-
- /*
- Una constante con el numero de recurso de la ventana que hemos creado
- empleando ResEdit
- */
- #define kMiVentanaRsrcID 128 /* Nº del recurso WIND */
-
- WindowPtr gMiVentana = nil; /* Variable de tipo 'pointer'.
- Puntero a una estructura
- de tipo WindowRecord definida por Apple
- en el fichero UNIVERSAL HEADER Windows.h
- y que corresponderá
- a la ventana que crearemos
- NOTA sólo para curiosos: De hecho,
- una variable WindowPtr apunta a la
- estructura GrafPort que forma parte de
- la estructura WindowRecord. */
-
-
-
- /*--------------------------------------------------------------------*/
- /* A PARTIR DE ESTE PUNTO, APARECE EL CODIGO DE LAS FUNCIONES CREADAS
- ESPECIFICAMENTE PARA ESTE PROGRAMA. */
- /*--------------------------------------------------------------------*/
-
-
-
- /**************************************************************** */
- /* main() */
- /**************************************************************** */
- /*
- Todos los programas en C poseen una función que debe llamarse main.
- (NO PERTENECE A LA TOOLBOX)
- Cuando un programa se pone en marcha, lo hace SIEMPRE ejecutando
- en primer lugar la función main().
- Es el punto de entrada a nuestra aplicación.
-
- Recibe: nada
- Que hace: Crea menús y pone una ventana en pantalla etc...
- Salida: void (nada)
- */
- void main (void)
- {
- /* Antes de hacer nada, debemos inicializar la Toolbox del Mac */
- /* Como sea que el procedimiento a seguir para inicializar la Toolbox */
- /* es casi siempre el mismo, hemos creado una función MF_InitToolbox()*/
- /* que contiene las llamadas estándar de inicialización */
-
- MF_InitToolbox();
-
- /* Ahora debemos preparar y mostrar la barra de menú, que contendrá */
- /* los menús propios de nuestra aplicación */
-
- MF_SetupMenus();
-
- /* Ahora empleamos una función se encargará de abrir una ventana */
- MF_AbreMiVentana();
-
- /* Una vez abierta la ventana, podemos escribir algo de texto en ella */
- MF_EscribeTexto();
-
- /* Y ya podemos entrar en el bucle principal, que se encargará de
- recoger e interpretar las acciones del usuario */
- MF_bucle_principal();
-
- /* Cuando el bucle principal haya terminado, será porque el usuario
- desea acabar el programa.
- Debemos liberar la memoria ocupada por nuestra ventana. */
- DisposeWindow(gMiVentana);
-
- /* Y ya está, al acabarse la función main(), el Sistema cerrará
- nuestra aplicación de forma automática */
-
- } /* Fin de main() y del programa */
-
-
-
- /**************************************************************** */
- /* MF_bucle_principal */
- /**************************************************************** */
- /*
- Recibe: nada
- Que hace: Entra en un bucle y espera que se produzca una acción (evento)
- Según cual sea este, reacciona llamando una de las funciones que
- hemos creado en esta demo.
- Salida: nada
- */
- void MF_bucle_principal(void)
- {
- /* Declaramos una variable del tipo EventRecord que llamaremos el_Evento */
- EventRecord el_Evento;
- /*
- Un EventRecord es una estructura declarada
- por Apple en el fichero UNIVERSAL HEADER
- Events.h y formada por las siguientes
- variables:
-
- struct EventRecord {
- EventKind what; (qué evento)
- UInt32 message; (datos del evento)
- UInt32 when; (cuando se produce)
- Point where; (coordenadas del evento)
- EventModifiers modifiers;(estado de las teclas
- especiales: CMD, Opt, etc...)
- };
- */
-
- WindowPtr la_ventana; /* Guardaremos un puntero que nos indicará en que
- ventana (si es el caso) se ha producido un evento */
-
-
- short zona_de_la_ventana; /* También guardaremos el código que indica
- la zona de la ventana en que se produce un evento
- si es del tipo mouseDown
- */
-
-
- Boolean hay_evento; /* valor de salida de la función WaitNextEvent */
- /* Lo ignoraremos en esta demo */
-
- while (gAcabarProg == false)
- /* Mientras la variable global gAcabarProg sea falsa, repetiremos este bucle */
- /* Cuando es usuario seleccione 'Salir' del menú Archivo, cambiaremos el */
- /* valor de gAcabarProg a true (cierto) */
- {
-
- hay_evento = WaitNextEvent(everyEvent, &el_Evento, 0L, 0L);
- /* WaitNextEvent es una función de la ToolBox que nos proporciona
- información acerca de las posibles acciones del usuario o eventos del
- Sistema. Para ello, 'llena' de información las variables de la estructura
- EventRecord (el_Evento, en nuestro caso) */
-
- switch(el_Evento.what)
- {
- case nullEvent:
- /* Ignoramos eventos nulos (ningún evento).*/
- break;
-
- case keyDown:
- /* Se ha pulsado una tecla. Comprobaremos si también se ha pulsado
- la tecla de CMD y si es así, llamaremos la función que responde
- a la selección de opciones de menú */
- if(el_Evento.modifiers & cmdKey) /* Tecla de CMD pulsada? */
- {
- MF_MenuBar(MenuKey( el_Evento.message & charCodeMask) ) ;
- }
- break;
-
- case autoKey:
- /* Ignoramos los eventos de repetición, generados al mantener
- pulsada una tecla */
- break;
-
- case mouseDown:
- /* clic del ratón en algún sitio...*/
- zona_de_la_ventana = FindWindow(el_Evento.where,&la_ventana);
- switch (zona_de_la_ventana)
- {
- case inDrag:/* clic en la barra de título. Para que el usuario */
- /* pueda arrastrar la ventana, simplemente hemos de */
- /* usar la función DragWindow() que se encarga del */
- /* proceso, hasta que se suelte el botón del ratón */
- DragWindow(la_ventana,el_Evento.where,&qd.screenBits.bounds);
- break;
-
- case inMenuBar: /* clic en la barra de menús */
- MF_MenuBar(MenuSelect(el_Evento.where));
- break;
-
- default:
- /* Ignoramos clics en otras zonas de la ventana */
- break;
- }
- break;
-
- case mouseUp:
- /* ignoraremos los eventos producidos al soltar el botón del ratón */
- break;
-
- case diskEvt:
- /* También ignoraremos los eventos producidos al insertar un disco */
- break;
-
- case updateEvt:
- /* Una ventana debe ser refrescada. Llamamos la función
- MF_Update, pasándole un puntero a la ventana en cuestión.
- La variable message de la estructura EventRecord, contiene
- dicho puntero, pero es necesario forzar (cast) su tipo al
- de WindowPtr */
- la_ventana = (WindowPtr)el_Evento.message;
- MF_Update( la_ventana );
- break;
-
- default:
- /* En cualquier otro caso, ignoramos el evento */
- break;
-
- } /* Fin de switch(el_Evento.what) */
-
- } /* Fin de while (gAcabarProg == false) */
-
-
- } /* Fin de la función MF_bucle_principal() */
-
-
-
- /**************************************************************** */
- /* MF_Update */
- /**************************************************************** */
- /*
- Esta función se emplea cuando MF_bucle_principal ha detectado un evento
- del tipo updateEvt. El sistema lo genera cuando una ventana activa
- es desplazada o cuando una ventana que no era la activa es activada.
- En estos casos, la zona de la ventana que permanecía
- oculta por otras ventanas debe ser refrescada, re-dibujando su contenido.
- El sistema controla todas las ventanas abiertas y genera un evento updateEvt
- cuando alguna zona de una ventana necesita ser refrescada.
-
- Recibe: un puntero a la ventana que debe ser refrescada.
- Que hace: Esta demo aprovecha la función MF_EscribeTexto(). Cuando la ventana
- necesita refrescarse, simplemente llamamos de nuevo MF_EscribeTexto()
- y la ventana se actualizará.
-
- Salida: void (nada)
- */
- void MF_Update( WindowPtr ventana_a_refrescar)
- {
-
- GrafPtr old_port; /* Declaración de una variable de tipo
- puntero (pointer) a un área gráfica */
-
- GetPort( &old_port ); /* Preservamos el área gráfica actual */
-
- SetPort( ventana_a_refrescar ); /* Cambiamos de área, seleccionando la
- correspondiente a la ventana que debe
- refrescarse */
-
- BeginUpdate( ventana_a_refrescar );
-
- /* Aqui deberíamos llamar las funciones adecuadas para re-dibujar los
- contenidos de nuestra ventana. En este caso re-escribimos un texto
- en la ventana
- */
-
- MF_EscribeTexto();
-
- EndUpdate( ventana_a_refrescar );
-
- SetPort( old_port ); /* recuperamos el área gráfica inicial */
-
- } /* Fin de MF_Update() */
-
-
-
- /**************************************************************** */
- /* MF_MenuBar */
- /**************************************************************** */
- /*
- Esta función reacciona cuando MF_bucle_principal ha detectado que el clic
- del ratón se ha producido en la barra de menús de nuestro programa.
-
- Requiere: Un recurso de tipo ALRT en el fichero CdeCerca_4.µ.rsrc
- Recibe: una variable con la información del menu e item seleccionados
- Que hace: Actúa en función de la posible selección de un item de alguno
- de nuestros menús.
- Salida: void (nada)
- */
- void MF_MenuBar(long algoSeleccionado)
- {
- short Que_Menu;
- short Que_Opcion;
- short dummy;
- Str255 ItemName;
- GrafPtr oldPort;
-
- if(algoSeleccionado != 0L)
- {
- /* algoSeleccionado es un valor de tipo long (4 bytes)
- que contiene en los 2 bytes superiores el número de menú seleccionado
- y en los dos bytes inferiores, el número de la opción seleccionada
- de dicho menú.
- Para extraer ambos valores, emplearemos una funciones de la Toolbox,
- HiWord y LoWord que nos devolverán los valores que nos interesan */
-
- Que_Menu = HiWord(algoSeleccionado); /* 2 bytes superiores */
- Que_Opcion = LoWord(algoSeleccionado);/* 2 bytes inferiores */
-
- switch(Que_Menu)
- {
- case kAppleMenuID: /* Menú Apple (nuevo) */
- if(Que_Opcion == kAcercaDe_Item) /* Si es la opción 'Acerca de' */
- {
- /* Empleamos la función Alert() de la Toolbox, para que el Sistema
- abra un cuadro de diálogo que hemos creado previamente usando
- ResEdit, como recurso de tipo ALRT.
- La función Alert() pasa el control de nuestro programa al Sistema
- y no nos lo devuelve hasta que el usuario haya cerrado la ventana de
- alerta
- */
- Alert(kAlertRsrcID,nil); /* Todo parado... */
- }
- else
- /* NO es la opción 'Acerca de'. Ha de ser algo del menú Apple */
- /* Puede ser cualquier cosa... carpetas, aplicaciones, documentos...*/
- {
- /* 1º Obtenemos el nombre del item seleccionado */
- GetItem(gAppleMenu,Que_Opcion, ItemName);
-
- GetPort(&oldPort);
-
- /* 2º Lo abrimos empleando la función OpenDeskacc() que */
- /* funcionará sea cual sea el tipo de objeto del menú Apple */
- /* seleccionado por el usuario. Podemos ignorar el valor que */
- /* OpenDeskAcc() devuelve */
- dummy = OpenDeskAcc(ItemName);
-
- SetPort(oldPort);
- }
- break;
-
- case kArchivoMenuID: /* Menú Archivo */
- switch(Que_Opcion)
- {
- case kSalirItem: /* Opción 'Salir' */
- gAcabarProg = true; /*IMPORTANTE: Cambiamos el valor de
- la variable global que nos indica
- que debemos finalizar el programa */
- break;
-
- } /* Fin de switch(Que_Opcion) */
-
- break;
- } /* Fin de switch(Que_Menu) */
-
- HiliteMenu(0);
-
- } /* Fin de if(algoSeleccionado != 0L) */
-
- } /* Fin de función MF_MenuBar() */
-
-
-
- /**************************************************************** */
- /* MF_InitToolbox */
- /**************************************************************** */
- /*
- Inicializa la Toolbox Macintosh. El orden de llamada a las diversas
- rutinas es significativo! No lo cambie.
-
- Requiere: nada
- Recibe: nada
- Cambia: nada en la aplicación
- Salida: nada
- */
- void MF_InitToolbox (void)
- {
- InitGraf(&qd.thePort);
- InitFonts();
- FlushEvents(everyEvent,0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor();
-
- } /* Fin de MF_InitToolbox() */
-
-
-
- /**************************************************************** */
- /* MF_SetupMenus */
- /**************************************************************** */
- /*
- Inicializa y muestra los menús del programa.
-
- Requiere: Recursos de tipo MENU en el fichero CdeCerca_4.µ.rsrc
- Concretamente los recursos MENU nº 128 y 129
- Recibe: nada
- Cambia: asigna valor a las globales e instala el menú en la barra de menús
- Salida: nada
- */
- void MF_SetupMenus(void)
- {
-
- /* Primero, leer los recursos de menu */
- gAppleMenu = GetMenu( kAppleMenuID );
- gArchivoMenu = GetMenu( kArchivoMenuID );
-
- /* Nuevo: Añadir, al menú Apple todo los que ya contiene... */
- /* La función AppendResMenu() añade a un menú, los nombres de todos */
- /* los recursos del tipo especificado como parámetro. En este caso 'DRVR' */
- /* Qye resultan ser los items del menú Apple, ya sean programas, documentos */
- /* etc... */
- AppendResMenu( gAppleMenu, 'DRVR' );
-
- InsertMenu(gAppleMenu, 0);
- InsertMenu(gArchivoMenu, 0);
-
- DrawMenuBar();
-
- } /* Fin de MF_SetupMenus() */
-
-
-
- /**************************************************************** */
- /* MF_AbreMiVentana */
- /**************************************************************** */
- /*
- Abre la ventana (la única) de nuestro programa. A diferencia de las anteriores
- versiones, en esta la ventana ha sido creada previamente empleando ResEdit
- y guardada en el fichero de recursos CdeCerca_4.µ.rsrc.
- Durante la compilación, los recursos de dicho fichero son copiados e
- integrados en la aplicación resultante, quedando así en disposición de ser
- empleados por la aplicación.
-
- Requiere: Recurso WIND 128 (En CdeCerca_4.µ.rsrc)
- Recibe: nada
- Que hace: Crea una ventana...
- Salida: void (nada)
- */
- void MF_AbreMiVentana(void)
- {
-
- /*
- En vez de usar la función NewWindow(), empleamos la función
- GetNewWindow() que crea una ventana leyendo el formato de la misma
- contenido en un recurso WIND, dentro de los recursos de la aplicación.
-
- GetNewWindow requiere los siguientes parámetros:
-
- GetNewWindow(short windowID, void *wStorage, WindowRef behind)
- Por el momento, el único al que nos referiremos es:
- windowID: El número de recurso del tipo WIND definiendo la ventana.
-
- */
- gMiVentana = GetNewWindow(kMiVentanaRsrcID, nil, (WindowPtr)-1L);
-
- if(gMiVentana == nil)
- ExitToShell(); /* Si la creación de la ventana falla,
- posiblemente sea debido a falta de memoria libre
- Lo más aconsejable es salir de la aplicación */
-
- } /* fin de MF_AbreMiVentana() */
-
-
-
- /****************************************************************/
- /* MF_EscribeTexto */
- /****************************************************************/
- /*
- Dibuja en nuestra ventana un texto.
-
- Recibe: nada
- Cambia: Dibuja en la ventana un texto.
- Salida: nada
- */
- void MF_EscribeTexto(void)
- {
- MoveTo(30,30);
- DrawString("\pMacFormat - C de Cerca nº 4");
-
- }